import React, { useState, useCallback, useMemo } from 'react';
import { Common } from "UtilsCommon";
import { useGetDataSourceOptions } from 'UseHooks';
import { Checkbox } from 'antd-mobile';
import Base from './base';

const getTreeNode = (property, parentValue) => {
    Base.setValueTextName(property);
    const { parentValueName, valueName, textName } = property;

    const dataList = property.dataSource.filter(f => Common.isEquals(f[parentValueName], parentValue));

    const nodeList = []; let node = null; let children = null;

    dataList.forEach(m => {
        const value = m[valueName];
        const parentValue = m[parentValueName];
        node = { label: m[textName], value, parentValue };
        children = getTreeNode(property, value);
        if (children.length > 0) node.children = children;
        nodeList.push(node);
        property.nodes[value] = node;
    });

    return nodeList;
};

const getOptions = (property, view, pageAxis, parentValue) => {
    if (property.isOptionDataSource) return property.dataSource;
    property.nodes = {};
    return getTreeNode(property, property.rootValue);
};

const setChildNodesChecked = (node) => {
    if (node.children) {
        node.children.forEach(c => {
            c.checked = node.checked;
            setChildNodesChecked(c);
        });
    }
};

const setParentNodesChecked = (property, node) => {
    const parentNode = property.nodes[node.parentValue];

    if (parentNode) {
        let checked = true;
        for (let i = 0; i < parentNode.children.length; i++) {
            if (!parentNode.children[i].checked) {
                checked = false;
                break;
            }
        }
        parentNode.checked = checked;
        if (checked) setParentNodesChecked(property, parentNode);
    }
};

const renderOption = (property, m, i, onChange, value) => {
    if (property.isSetValue) {
        const parentNode = property.nodes[m.parentValue];
        if (parentNode && parentNode.checked) m.checked = true;
        else m.checked = value.includes(m.value);
    }
    else if (property.isSingle) {
        m.checked = value.includes(m.value);
    }

    return <div className='divNode' key={i}>
        <div className='divCheckBox2'><Checkbox checked={m.checked} onChange={(c) => {
            m.checked = c;
            if (!property.isSingle) {
                setChildNodesChecked(m);
                setParentNodesChecked(property, m);
            }
            onChange(m);
        }}>{m.label}</Checkbox></div>
        <div className='divNodes'>
            {m.children && renderOptions(property, m.children, onChange, value)}
        </div>
    </div>;
};

const renderOptions = (property, options, onChange, value) => {
    return options.map((m, i) => renderOption(property, m, i, onChange, value));
};

const getValue = (property, v, isSetValue) => {
    property.isSetValue = isSetValue;
    if (Common.isNullOrEmpty(v) && !Common.isNullOrEmpty(property.defaultValue)) {
        return property.defaultValue.split(',');
    }
    if (!v) return [];
    if (property.isArray) return v;
    return v.join(',');
};

const getNodeValues = (nodes) => {
    const list = [];
    for (const key in nodes) {
        if (nodes[key].checked) list.push(nodes[key].value);
    }

    return list;
};

export default (props) => {
    const { property, view, pageAxis } = Base.getProps(props);

    const initValue = useMemo(() => getValue(property, property.value, !property.isSingle), [property]);
    const [value, setValue] = useState(initValue);
    const [isVisible, setIsVisible] = useState(property.isVisible !== false);
    const [options, setOptions] = useGetDataSourceOptions(property, view, pageAxis, getOptions, property.id);

    const onChange = useCallback((n) => {
        property.isSetValue = false;
        if (property.isSingle) {
            setValue([n.value]);
            property.selectNode && property.selectNode(n);
        }
        else {
            setValue(getNodeValues(property.nodes));
        }
    }, [setValue, value, property]);

    property.setIsVisible = (v) => { property.isVisible = v; setIsVisible(v); };
    property.setValue = (v) => {
        property.isSetValue = true;
        setValue(v || []);
    };
    property.getValue = () => getValue(property, value);
    property.setOptions = (v) => setOptions(v);
    property.refreshOptions = () => setOptions(getOptions(property, view, pageAxis));

    if (!isVisible) return null;

    let valueList = Common.isNullOrEmpty(value) ? [] : value;
    if (!Common.isArray(valueList)) valueList = valueList.split(",");

    if (options.length === 0) return null;

    const { style, labelStyle, label, isAddColon, className, isNullable, isRed } = property;

    const isRed2 = isNullable === false && isRed;

    return <div style={Base.setStyle(style)} className={className}>
        {label && <div className='divLabel' style={Base.setStyle(labelStyle)}>
            {isRed2 ? <span style={{ color: 'red', position: 'relative', paddingRight: '0.125rem', top: '0.125rem' }}>*</span> : ''}
            {label}{isAddColon ? '：' : ''}
        </div>}
        <div className='divList'>
            {renderOptions(property, options, onChange, value)}
        </div>
    </div>;
};